Instalar librerias necesarias (en modo silencioso -q) e ignorar errores una vez que este activado el enviroment min 431 en tu computador

[ ]:
!wget -q https://raw.githubusercontent.com/arqlm/arqlm.github.io/main/_static/libraries.txt
!pip install -q -r /content/libraries.txt
!pip install -q --upgrade plotly[kaleido]
!rm -r /content/libraries.txt
!rm -r /content/sample_data/ ## Esta linea no es necesaria cuando no se trabaja en colab.google
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 7.9/7.9 MB 35.8 MB/s eta 0:00:00
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 51.5/51.5 kB 1.7 MB/s eta 0:00:00
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 9.6/9.6 MB 64.7 MB/s eta 0:00:00
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 51.3/51.3 kB 2.9 MB/s eta 0:00:00

[ ]:
## Importar librerias

import pandas as pd
import numpy as np

# Import packages

import base64
import datetime
import io

import plotly.io as pio
# pio.renderers.default = "colab"
pio.renderers.default = "notebook" # usar esta linea en jupyter notebook o vscode
import plotly.graph_objects as go
import plotly.express as px
import plotly.offline as py


1. Despliegue de datos

El despliegue de los datos permite visualizar su ubicación en el espacio. Cuando se trabaja en el espacio tridimensional, el despliegue puede hacerse con proyecciones (plantas y secciones) o vistas en perspectiva. Los mapas de datos pueden incluir información sobre los valores medidos y así dar una idea preliminar de la distribución y continuidad espacial de la variable en estudio, por ejemplo, utilizando símbolos de forma o tamaño variable o escalas de colores/de grises (Figura 1).

1.1. Carga de archivos

[ ]:
import pandas as pd
import numpy as np

# Cargar base de datos en pandas
DH = pd.read_csv('EvYacData.csv', sep=',', encoding='latin1')
DH

Este Norte Elevación au_ppm ag_ppm cu_pct aucn_ppm cucn_ppm Zmin Alte Lito
0 472186.686 6925804.447 4220.763 -99.00 -99.0 -99.000 -99.0 -99.0 OXI ILL_CLO IBX_MM
1 472187.202 6925805.493 4213.861 0.30 2.3 0.011 -99.0 -99.0 OXI ILL_CLO IBX_MM
2 472187.343 6925805.770 4211.986 0.47 16.2 0.032 -99.0 -99.0 OXI ILL_CLO IBX_MM
3 472187.493 6925806.060 4210.013 0.31 2.3 0.018 -99.0 -99.0 OXI ILL_CLO IBX_MM
4 472187.642 6925806.351 4208.040 0.29 2.1 0.010 -99.0 -99.0 OXI ILL_CLO IBX_MM
... ... ... ... ... ... ... ... ... ... ... ...
77836 471293.198 6925823.101 3761.674 0.03 1.0 0.002 -99.0 -99.0 BACK PROP ECS
77837 471293.540 6925824.040 3759.942 0.01 0.7 0.001 -99.0 -99.0 BACK PROP ECS
77838 471293.882 6925824.980 3758.209 0.01 0.4 0.001 -99.0 -99.0 BACK PROP ECS
77839 471294.224 6925825.920 3756.477 0.06 1.3 0.004 -99.0 -99.0 BACK PROP ECS
77840 471294.607 6925826.972 3754.538 0.06 0.5 0.003 -99.0 -99.0 BACK PROP ECS

77841 rows × 11 columns

1.2. Visualización de datos (DH)

[202]:
continuous = 'cu_pct'

import plotly.io as pio
# pio.renderers.default = "colab"
pio.renderers.default = "notebook" # usar esta linea en jupyter notebook o vscode
import plotly.graph_objects as go
import plotly.express as px
import plotly.offline as py

fig = go.Figure(data=[go.Scatter3d(
    x=DH['Este'],
    y=DH['Norte'],
    z=DH['Elevación'],
    marker=dict(color=DH[continuous],
                colorscale=px.colors.sequential.Rainbow[1:],
                cmin=0.0,
                cmax=DH[continuous].quantile(0.95),
                size=2.0, # Esta opcion controla el tamaño de los datos
                colorbar=dict(
                    title='Cu [%]',
                    thickness=20,
                    # Add a border to the colorbar
                    outlinecolor='black',  # Color of the border
                    outlinewidth=2,       # Width of the border
                    bordercolor='white',   # Background border color (if applicable)
                    borderwidth=1         # Background border width
                )
                ),
    mode='markers',
    opacity=1
)])

# otras opciones para controlar el color de los elementos de la figura
fig.update_layout(scene = dict(
                    xaxis = dict(
                        title='Este',
                        backgroundcolor="white",
                        gridcolor="gray",
                        showbackground=True,
                        zerolinecolor="white",),
                    yaxis = dict(
                        title='Norte',
                        backgroundcolor="white",
                        gridcolor="gray",
                        showbackground=True,
                        zerolinecolor="white"),
                    zaxis = dict(
                        title='Elevación',
                        backgroundcolor="white",
                        gridcolor="gray",
                        showbackground=True,
                        zerolinecolor="white",),
                    ),
                    font_family="Times New Roman",
                    font_color="black", hovermode=False
                  )
fig.show()

Figura 1: Mapa de datos de leyes de cobre. La escala de colores se refiere a la concentración de cobre expresada en porcentaje.

En caso de querer exportar la figura, puede usar el siguiente código

[ ]:
import kaleido
kaleido.get_chrome_sync()
fig.write_image('image.pdf',scale=6, width=1080, height=1080)

## Mas documentación
## https://github.com/plotly/Kaleido

Es importante también desplegar algunas visualización de la data en los distintos planos más importantes, como se muestra en la Figura 2 (XY: vista en planta, XZ: vista mirando hacia el Norte, e YZ: vista mirando hacia el Este). Para facilitar este despliegue de la información, se suele utilizar la función scatter plot (en 2 dimensiones) disponible en distintas librerías de visualización. Un scatter plot requiere tres variables: dos coordenadas mas el valor a desplegar en aquella coordenada.

[203]:
from plotly.subplots import make_subplots
DH_RF = DH.sample(frac=0.1) # Selects 10% of the rows (random fraction)

continuous = 'cu_pct'

# Initialize figure with subplots
fig = make_subplots(
    rows=2, cols=2,
    column_widths=[0.65, 0.35],
    row_heights=[0.5, 0.5],
    specs=[[{"type": "scatter", "rowspan": 2}, {"type": "scatter"}],
           [            None                    , {"type": "scatter"}]])

fig.add_trace(
go.Scatter(
    x=DH_RF['Este'],
    y=DH_RF['Norte'],
    marker=dict(color=DH_RF[continuous],
                colorscale=px.colors.sequential.Rainbow[1:],
                cmin=0.0,
                cmax=DH_RF[continuous].quantile(0.95),
                size=2.0, # Esta opcion controla el tamaño de los datos
                line=dict(
                    color='black',
                    width=0.05
                ),
                ),
    mode='markers',
    opacity=1, showlegend=False
),row=1, col=1
)

fig.add_trace(
go.Scatter(
    x=DH_RF['Este'],
    y=DH_RF['Elevación'],
    marker=dict(color=DH_RF[continuous],
                colorscale=px.colors.sequential.Rainbow[1:],
                cmin=0.0,
                cmax=DH_RF[continuous].quantile(0.95),
                size=2.0, # Esta opcion controla el tamaño de los datos
                line=dict(
                    color='black',
                    width=0.05
                ),
                ),
    mode='markers',
    opacity=1, showlegend=False
),row=1, col=2
)

fig.add_trace(
go.Scatter(
    x=DH_RF['Norte'],
    y=DH_RF['Elevación'],
    marker=dict(color=DH_RF[continuous],
                colorscale=px.colors.sequential.Rainbow[1:],
                cmin=0.0,
                cmax=DH_RF[continuous].quantile(0.95),
                size=2.0, # Esta opcion controla el tamaño de los datos
                line=dict(
                    color='black',
                    width=0.05
                ),
                colorbar=dict(
                    title='Cu [%]',
                    thickness=20,
                    # Add a border to the colorbar
                    outlinecolor='black',  # Color of the border
                    outlinewidth=2,       # Width of the border
                    bordercolor='white',   # Background border color (if applicable)
                    borderwidth=1         # Background border width
                )
                ),
    mode='markers',
    opacity=1, showlegend=False
),row=2, col=2
)

# Update xaxis properties
fig.update_xaxes(title_text="Este", range=[DH['Este'].quantile(0.02), DH['Este'].quantile(0.99)], gridcolor="gray", row=1, col=1)
fig.update_xaxes(title_text="Este", gridcolor="gray", row=1, col=2)
fig.update_xaxes(title_text="Norte", gridcolor="gray", range=[DH['Norte'].quantile(0.03), DH['Norte'].quantile(0.99)], row=2, col=2)

# Update yaxis properties
fig.update_yaxes(title_text="Norte", range=[DH['Norte'].quantile(0.02), DH['Norte'].quantile(0.995)], gridcolor="gray", row=1, col=1)
fig.update_yaxes(title_text="Elevación", gridcolor="gray", row=1, col=2)
fig.update_yaxes(title_text="Elevación", gridcolor="gray", row=2, col=2)

# otras opciones para controlar el color de los elementos de la figura
fig.update_layout(font_family="Times New Roman",
                    font_color="black", plot_bgcolor='white', hovermode=False)

fig.show()

## Mas documentación
## https://plotly.com/python/subplots/

Figura 2: Mapa de locación, proyectando la data en los tres planos principales.

Con la informacion desplega en 2 y 3 dimensiones ya podemos empezar a obtener algunas conclusiones sobre la campaña de muestreo:

  • varios sondajes se han dispuesto en forma vertical pero tambien algunos de ellos estan inclinados, y

  • el espaciamiento entre sondajes parace ser bastante regular en la zona central del deposito, mientras que la densidad de muestras decrece hacia los bordes;

asi como de nuestro yacimiento en general:

  • Las mejores leyes se encuentran en la zona central pero a partir de unos 400 a 500 metros de profundidad (diferencia entre la cota superior de 4500m y la cota 4000m)

  • La calidad de las leyes decrece hacia los bordes del yacimiento.

  • No se visualiza un aumento sostenido de leyes (tendendia) en ninguna direccion en particular

¿Tendrá un impacto económico decisivo en este proyecto minero la gran profundidad a la que se encuentran las leyes? Esto solo se podrá concluir en forma rotunda una vez que se haya desicido un método de explotación y contemos con un plan minero.

Finalmente, para confirmar estas afirmaciones, procedemos a hacer cortes, solo en vista en planta (Figura 3). Puedes hacer lo mismo en secciones transversales.

Usaremos la libreria numpy para crear un arreglo de números que se encuentren dentro de los límites en la vertical de nuestro depósito.

[204]:
import numpy as np

ROWS = 3
COLS = 2
# Crear listado de bancos
step_size = 15
max_benches = ROWS*COLS
lims = np.arange(4250,4250-step_size*max_benches,-step_size)
lims
[204]:
array([4250, 4235, 4220, 4205, 4190, 4175])
[205]:
import plotly.graph_objects as go
import plotly.express as px

continuous = 'cu_pct'

# Initialize figure with subplots
# Initialize figure with subplots
fig = make_subplots(
    rows=ROWS, cols=COLS, horizontal_spacing=0.2, vertical_spacing=0.1,
    subplot_titles=[f"Cu [%], banco {lims[i]+step_size/2}" for i in range(len(lims))]
)

for i, lim in enumerate(lims):
    data_temp = DH.loc[(DH['Elevación'] > lim) & (DH['Elevación'] <= lim + step_size)]
    # Calculate row and column indices for the subplot (1-based indexing)
    row = i // COLS + 1
    col = i % COLS + 1

    fig.add_trace(
        go.Scatter(
            x=data_temp['Este'],
            y=data_temp['Norte'],
            marker=dict(
                color=data_temp[continuous],
                colorscale=px.colors.sequential.Rainbow[1:],
                cmin=0.0,
                cmax=data_temp[continuous].quantile(0.95),
                size=2.0,
                line=dict(
                    color='black',
                    width=0.05
                ),
            ),
            mode='markers',
            opacity=1,
            showlegend=False
        ),
        row=row, col=col
    )

    # Update xaxis properties
    fig.update_xaxes(title_text="Este", range=[DH['Este'].quantile(0.015), DH['Este'].quantile(0.97)], gridcolor='rgba(0,0,0,0.2)', row=row, col=col)

    # Update yaxis properties
    fig.update_yaxes(title_text="Norte", range=[DH['Norte'].quantile(0.03), DH['Norte'].quantile(0.99)], gridcolor='rgba(0,0,0,0.2)', row=row, col=col)

fig.update_annotations(font_size=12)
# otras opciones para controlar el color de los elementos de la figura
fig.update_layout(font_family="Times New Roman",font_size=8,
                    font_color="black", plot_bgcolor='white',   autosize = False,
    width = 600,
    height = 900,)


fig.show()

Figura 3: Vistas en planta de las leyes de cobre por banco. Cada corte abarca 15 [m] en profundidad.

La secciones en planta desplegadas son útiles al momento de reportar información en reportes físicos. Sin embargo, también es posible generar secciones en forma interactiva de modo de adquirir mayor intuición sobre el yacimiento (Figura 4).

[207]:
import plotly.graph_objects as go
import numpy as np

# Aumentamos el número de bancos
step_size = 15
inicio = DH['Elevación'].quantile(0.95)
fin = DH['Elevación'].quantile(0.05)
lims = np.linspace(inicio,fin,50) # fijamos esta vez el numero de bancos a mostrar a 10


# Create figure
fig = go.Figure()

for i, lim in enumerate(lims):
    data_temp = DH.loc[(DH['Elevación'] > lim) & (DH['Elevación'] <= lim + step_size)]

    fig.add_trace(
        go.Scatter(
            visible=False,
            x=data_temp['Este'],
            y=data_temp['Norte'],
            showlegend=False,
            marker=dict(color=data_temp[continuous],
                        colorscale=px.colors.sequential.Rainbow[1:],
                        cmin=0.0,
                        cmax=DH[continuous].quantile(0.95),
                        size=10, # Esta opcion controla el tamaño de los datos

                        colorbar=dict(
                            title='Cu [%]',
                            thickness=20,
                            # Add a border to the colorbar
                            outlinecolor='black',  # Color of the border
                            outlinewidth=2,       # Width of the border
                            bordercolor='white',   # Background border color (if applicable)
                            borderwidth=1         # Background border width
                        ),
                        line=dict(
                            color='rgba(0,0,0,1)',
                            width=1
                        ),
                        ),
            mode='markers',
            opacity=1
        ),
    )

    # Update xaxis properties
    fig.update_xaxes(title_text="Este", range=[DH['Este'].quantile(0.015), DH['Este'].quantile(0.97)], gridcolor='rgba(0,0,0,0.2)')

    # Update yaxis properties
    fig.update_yaxes(title_text="Norte", range=[DH['Norte'].quantile(0.03), DH['Norte'].quantile(0.99)], gridcolor='rgba(0,0,0,0.2)')

    fig.update_annotations(font_size=14)
    # otras opciones para controlar el color de los elementos de la figura
    fig.update_layout(font_family="Times New Roman",font_size=14,
    font_color="black", plot_bgcolor='white',   autosize = False,
    width = 700,
    height = 900,)

# Make 0th trace visible
fig.data[0].visible = True

# Create and add slider
steps = []
for i, lim in enumerate(lims):
    step = dict(
        method="update",
        args=[{"visible": [False] * len(fig.data)},
        {"title": "Banco: " + f"{lim:.1f}" + " m"},],  # Format to 1 decimal place
        label=f"{lim:.1f}")  # Format to 1 decimal place
    step["args"][0]["visible"][i] = True
    steps.append(step)

sliders = [dict(
    active=0,
    currentvalue={"prefix": "Banco: "},
    pad={"t": 50},
    steps=steps
)]

fig.update_layout(
    sliders=sliders
)

fig.show()

Figura 4: Vista dinámica de plantas mostrando las leyes de cobre por banco. Cada corte abarca 15 [m] en profundidad.